/*
 *  Author: chival366
 *  QQ: 794960056
 *  Email: 794960056@qq.com; chival366@qq.com
 *  Source: github.com/chival366
 *  Copyright (c) 2020 The Goke project authors. All Rights Reserved.
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
package com.goke.media.call;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.goke.media.R;
import com.goke.media.jni.C2JavaAPI;
import com.goke.media.jni.Java2CAPI;
import com.goke.media.jni.SDPInfo;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;

public class CallActivity extends Activity implements IStateListener {
	private static Java2CAPI j2c = null;

	String callInfoList = "";
	private EditText editTextCallee = null;
	private Button buttonAnswer = null;
	private Button buttonInvite = null;
	private Button buttonHangup = null;
	private TextView textViewVersion = null;
	private TextView textViewCallState = null;
	private TextView textViewMediaStats = null;

	private String username, password, testmode;
	private String caller, callee;
	
	private static String TAG = "cosdkj";
	// private SDPInfo localSDP = null;
	// private SDPInfo remoteSDP = null;
	SDPInfo voicelocal = null;
	SDPInfo videolocal = null;

	// SDPInfo voicelocalsdp = null, voiceremotesdp = null;
	private MediaEngine mediaEngine = null;
	
	private LinearLayout llRemoteSurface = null;
	private LinearLayout llLocalSurface = null;
	private SurfaceView svLocal = null;
	private SurfaceView svRemote = null;
	private int testMode = 0;
	private int hasVideo = 0, hasWan = 0;
	private int callid = -1;
	private String remoteuser = null;
	
	final static int VOICE = 0;
    final static int VIDEO = 1;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_call);
		editTextCallee = (EditText) findViewById(R.id.editTextCallee);
		buttonAnswer = (Button) findViewById(R.id.buttonL);
		buttonInvite = (Button) findViewById(R.id.buttonC);
		buttonHangup = (Button) findViewById(R.id.buttonR);

		textViewVersion = (TextView) findViewById(R.id.textViewVersion);
		textViewCallState = (TextView) findViewById(R.id.textViewCallState);
		textViewMediaStats = (TextView) findViewById(R.id.textViewMediaStats);

		Intent intent = getIntent();
		username = intent.getStringExtra("username");
		password = intent.getStringExtra("password");
		testmode = intent.getStringExtra("testmode");
		
	    PeerInfo.check(this, username != null, "username can't be null");
	    PeerInfo.check(this, password != null, "password can't be null");
	    PeerInfo.check(this, testmode != null, "testmode can't be null");
	    
		testMode = Integer.parseInt(testmode);
		
		hasVideo = ((testMode >> 1) & 1);
		hasWan = (testMode & 1);
         
         String localIP = PeerInfo.getLocalIP(this);
		if (localIP == null) {
			Log.e(TAG, "permission error. need set android.permission.INTERNET");
			return;
		}

		voicelocal = new SDPInfo(20000, localIP, "PCMA");
		//voiceremote = new SDPInfo(20000, localIP, "PCMA");
		
		if (hasVideo == 1) {
			llRemoteSurface = (LinearLayout) findViewById(R.id.llRemoteView);
			llLocalSurface = (LinearLayout) findViewById(R.id.llLocalView);
			textViewCallState.setVisibility(INVISIBLE);
			textViewCallState = null;

			videolocal = new SDPInfo(21000, localIP, "VP8");
			//videoremote = new SDPInfo(21000, localIP, "VP8");
			
		}
         
		editTextCallee.setText(localIP);

		buttonAnswer.setEnabled(false);
		buttonInvite.setEnabled(true);
		buttonHangup.setEnabled(false);
		Sound.Create( this );
		
		C2JavaAPI.setCallStateListener(this);

		j2c = new Java2CAPI();
		PeerInfo.check(this, j2c != null, "username can't be null");
		
		String sdkVersion = j2c.cosdkVersion();
    	textViewVersion.setText(sdkVersion + "\n\nLocalIP: " + localIP
				+ "\nSipUser: " + username);
		editTextCallee.setText(localIP);

		mediaEngine = new MediaEngine(this, j2c, hasVideo);

		j2c.cosdkInit();
		
		if(hasWan==1){
			editTextCallee.setText(username);
			j2c.cosdkReg("42.194.133.69", "",
					username, password);
		}
		
		j2c.setLocalSDP( voicelocal, VOICE );
		if(hasVideo==1){
			j2c.setLocalSDP( videolocal, VIDEO );
		}

		buttonInvite.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				buttonInvite.setEnabled(false);
				buttonHangup.setEnabled(true);
				callee = editTextCallee.getText().toString();
				Sound.StartPlay( "out" );

				callInfoList = "";
				mediaEngine.voiceStartRecv(voicelocal.port);
				if (hasVideo == 1) {
					textViewVersion.setVisibility(INVISIBLE);
					mediaEngine.videoStartRecv(videolocal.port,
							llLocalSurface, llRemoteSurface);
				}

				callid = j2c.cosdkInvite(callee);
				// j2c.mediaStartSend( voiceremotesdp.getPort(),
				// voiceremotesdp.getAddr(), voiceremotesdp.getCodec() );

				// Log.d( TAG, "click invite localaddr:port " +
				// voicelocalsdp.getAddr() + ":" + voicelocalsdp.getPort() );
				// Log.d( TAG, "click invite remoteaddr:port " +
				// voiceremotesdp.getAddr() + ":" + voiceremotesdp.getPort() );
			}
		});

		buttonAnswer.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				buttonAnswer.setEnabled(false);
				// buttonHangup.setEnabled( true );
				Sound.StopPlay();
                SDPInfo voiceremote = j2c.getRemoteSDP(VOICE);
                //Log.i(TAG, "SDPInfo "+voiceremote.port+" "+voiceremote.addr+" "+voiceremote.codec);
				PeerInfo.check(CallActivity.this, voiceremote.port > 0, "remote audio sdp port should not be zero");
				PeerInfo.check(CallActivity.this, voiceremote.addr.length() > 0, "remote audio sdp addr should not be empty");

				mediaEngine.voiceStartRecv(voicelocal.port);
				
				mediaEngine.voiceStartSend(voiceremote);
				
				if(hasVideo==1){
					SDPInfo videoremote = j2c.getRemoteSDP(VIDEO);
					PeerInfo.check(CallActivity.this, videoremote.port > 0, "remote video sdp port should not be zero");
					PeerInfo.check(CallActivity.this, videoremote.addr.length() > 0, "remote video sdp addr should not be empty");

					if(videoremote != null){
						textViewVersion.setVisibility(INVISIBLE);
						mediaEngine.videoStartRecv(videolocal.port, llLocalSurface, llRemoteSurface);
						
						mediaEngine.videoStartSend(videoremote);
					}
				}
			
				j2c.cosdkAnswer(-1);
			}
		});

		buttonHangup.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				buttonHangup.setEnabled(false);
				buttonInvite.setEnabled(true);
				
				mediaStopAll();
				j2c.cosdkHangup(-1);
				
			}
		});
	}

	public void onBackPressed() {
		finish();
	}

	@Override
	protected void onDestroy() {
		mediaStopAll();
		if(hasWan==1) {
			j2c.cosdkUnreg();
		}
		
		j2c.cosdkExit();

		mediaEngine.dispose();
		mediaEngine = null;
		super.onDestroy();
	}

	public void mediaStopAll() {
		Sound.StopPlay();
		mediaEngine.voiceStop();
		if (hasVideo == 1) {
			if (llLocalSurface != null && llRemoteSurface != null) {
				mediaEngine.videoStop(llLocalSurface, llRemoteSurface);
			}
			textViewVersion.setVisibility(VISIBLE);
		}
	}

	@Override
	public int SdkCallback(final int s, final int c, final String info,
			final String jsonData) {
		final EventType src = EventType.values()[s];
		final SipEvent code = SipEvent.values()[c];

		if (src == EventType.SIP_CALL || src == EventType.SIP_REGISTRATION) {
			Log.d(TAG, "java  SdkCallback s=" + src + " c=" + c + " code="
					+ code + " info=" + info);
			callInfoList += (info + "\n");
		}

		try {
			if (src == EventType.SIP_CALL) {
				if (code == SipEvent.SIP_CALL_INVITE
						|| code == SipEvent.SIP_CALL_ANSWERED) {
					JSONObject jsonObject = new JSONObject(jsonData);
					callid = jsonObject.getInt("callid");

					// only for call next time
					if(hasWan==1){
						remoteuser = jsonObject.getString("user");
					}else{
						JSONObject jsonObjectVoice = (JSONObject) jsonObject.get("voice");
						remoteuser = jsonObjectVoice.getString("addr");
					}
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}

		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (src == EventType.SIP_REGISTRATION) {
					if (textViewCallState != null)
						textViewCallState.setText(callInfoList);
				} else if (src == EventType.MEDIA_STATISTIC) { // mediaStatistics
					textViewMediaStats.setText(info);
				} else if (src == EventType.SIP_CALL) {

					SipEvent code = SipEvent.values()[c];
					Log.d(TAG, "java runOnUiThread s=" + src + " c=" + code
							+ " info=" + info);
					if (code == SipEvent.SIP_CALL_CLOSED
							|| code == SipEvent.SIP_CALL_MESSAGE_ANSWERED
							|| code == SipEvent.SIP_CALL_CANCELLED
							|| code == SipEvent.SIP_CALL_GLOBALFAILURE) {
						buttonAnswer.setEnabled(false);
						buttonHangup.setEnabled(false);
						buttonInvite.setEnabled(true);
						Sound.StopPlay();
					}
					switch (code) {
					/*
					 * case SIP_CALL_PROCEEDING: break;
					 */
					case SIP_CALL_INVITE:
						buttonAnswer.setEnabled(true);
						buttonInvite.setEnabled(false);
						buttonHangup.setEnabled(true);
						Sound.StartPlay( "in" );
						callInfoList = info + "\n";
						if(remoteuser!=null){
							editTextCallee.setText(remoteuser);
						}
						break;
					case SIP_CALL_ANSWERED:
						Sound.StopPlay();
					{
						SDPInfo voiceremote = j2c.getRemoteSDP(VOICE);
						mediaEngine.voiceStartSend( voiceremote );
						if (hasVideo == 1) {
							SDPInfo videoremote = j2c.getRemoteSDP(VIDEO);
							mediaEngine.videoStartSend( videoremote );
						}
					}
						break;

					/*
					 * case SIP_CALL_ACK: break;
					 */

					case SIP_CALL_CLOSED: // receive bye
						
						mediaStopAll();
						break;
					case SIP_CALL_MESSAGE_ANSWERED: // response of bye, did
													// return to -1, and tid add
													// 1
						buttonAnswer.setEnabled(false);
						buttonHangup.setEnabled(false);
						buttonInvite.setEnabled(true);
						break;
					case SIP_CALL_CANCELLED: // cancel

						break;
					case SIP_CALL_REQUESTFAILURE: // cancel

						break;
					case SIP_CALL_GLOBALFAILURE: // be refused recv 6xx
						mediaStopAll();
						break;
					default:
						break;
					}
					if (textViewCallState != null) {
						textViewCallState.setText(callInfoList);
					}
				}
			}
		});

		return 0;
	}

}
